package com.atguigu.gmall.cart.service.impl;

import com.atguigu.gmall.cart.service.CartService;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.execption.CartSizeOverException;
import com.atguigu.gmall.common.execption.GmallException;
import com.atguigu.gmall.common.result.ResultCodeEnum;
import com.atguigu.gmall.feign.product.SkuInfoFeignClient;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.product.SkuInfo;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 钟涛
 * @version 1.0
 * @description: TODO
 * @date 2021/12/22 14:20
 */
@Service
public class CartServiceImpl implements CartService {
    private ObjectMapper mapper = new ObjectMapper();
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private SkuInfoFeignClient skuInfoFeignClient;

    /**
     * 决定购物车用那个键
     *
     * @param userId
     * @param userTempId
     * @return
     */
    @Override
    public String determinCartKey(String userId, String userTempId) {
        String s = RedisConst.USER_CART_KEY_PREFIX + (StringUtils.isEmpty(userId) ? userTempId : userId);

        return s;
    }

    /**
     * 添加商品到指定购物车
     *
     * @param skuId
     * @param skuNum
     * @param cartKey
     */
    @Override
    public SkuInfo addSkuToCart(Long skuId, Integer skuNum, String cartKey) throws JsonProcessingException {

        checkCartSize(cartKey);

        SkuInfo skuInfo = skuInfoFeignClient.getSkuInfo(skuId);
        String json = (String) redisTemplate.opsForHash().get(cartKey, skuId.toString());
        if (StringUtils.isEmpty(json)) {
            //购物车从未添加过这个商品
            CartInfo cartInfo = convertSkuInfo2CartInfo(skuInfo, skuNum);
            redisTemplate.opsForHash().put(cartKey, skuId.toString(), mapper.writeValueAsString(cartInfo));

        } else {
            //购物车已经添加过这个商品，只需数量叠加
            CartInfo cartInfo = mapper.readValue(json, CartInfo.class);
            cartInfo.setSkuNum(cartInfo.getSkuNum() + skuNum);
            cartInfo.setUpdateTime(new Timestamp(System.currentTimeMillis()));
            //再看下实时价格
            cartInfo.setSkuPrice(skuInfo.getPrice());
            String newJson = mapper.writeValueAsString(cartInfo);
            redisTemplate.opsForHash().put(cartKey, skuId.toString(), newJson);
        }
        return skuInfo;
    }

    @Override
    public List<CartInfo> getCartList(String cartKet) {
        List<Object> values = redisTemplate.opsForHash().values(cartKet);
        if(!CollectionUtils.isEmpty(values)){
            List<CartInfo> collect = values.stream().map((item) -> {
                String json = item.toString();
                CartInfo cartInfo = null;
                try {

                    cartInfo = mapper.readValue(json, CartInfo.class);
                } catch (JsonProcessingException e) {
                    e.printStackTrace();
                }
                return cartInfo;
            }).sorted((o1,o2)->
                (int)(o2.getCreateTime().getTime() - o1.getCreateTime().getTime())
            ).collect(Collectors.toList());
            return collect;
        }
        return null;
    }

    @Override
    public void updateSkuNum(String cartKey, Long skuId, Integer num) throws JsonProcessingException {
        CartInfo cartInfo = getCartInfo(cartKey, skuId);
        cartInfo.setSkuNum(cartInfo.getSkuNum() + num);
        cartInfo.setUpdateTime(new Timestamp(System.currentTimeMillis()));
        //商品数据保存到redis
        saveCartInfo(cartKey,cartInfo);
    }

    @Override
    public CartInfo getCartInfo(String cartKey, Long skuId) throws JsonProcessingException {
        String json = (String)redisTemplate.opsForHash().get(cartKey, skuId.toString());
        return mapper.readValue(json,CartInfo.class);
    }

    @Override
    public void saveCartInfo(String cartKey, CartInfo cartInfo) throws JsonProcessingException {
        redisTemplate.opsForHash().put(cartKey,cartInfo.getSkuId().toString(),mapper.writeValueAsString(cartInfo));
    }

    @Override
    public void updateSkuStatus(String cartKey, Long skuId, Integer status) throws JsonProcessingException {
        //拿到商品
        CartInfo cartInfo = getCartInfo(cartKey, skuId);
        //修改内容
        cartInfo.setIsChecked(status);
        cartInfo.setUpdateTime(new Timestamp(System.currentTimeMillis()));
        //保存到redis中
        saveCartInfo(cartKey,cartInfo);
    }

    @Override
    public void deleteCartInfo(String cartKey, Long skuId) {
        redisTemplate.opsForHash().delete(cartKey,skuId.toString());
    }

    @Override
    public void mergeCart(String userId, String userTempId) throws JsonProcessingException {



        //1.需要判断是否需要合并购物车
        if(!StringUtils.isEmpty(userId) && !StringUtils.isEmpty(userTempId)){
            checkAllSize(userId,userTempId);
            //2.查询临时购物车中所有商品
            List<CartInfo> cartList = getCartList(RedisConst.USER_CART_KEY_PREFIX + userTempId);
            if(!CollectionUtils.isEmpty(cartList)){
                //临时购物车有数据
                for (CartInfo cartInfo : cartList) {
                    //每个临时购物车中的商品添加到用户购物车中
                    addSkuToCart(cartInfo.getSkuId(),cartInfo.getSkuNum(),RedisConst.USER_CART_KEY_PREFIX + userId);
                }
                //清空临时购物车
                redisTemplate.delete(RedisConst.USER_CART_KEY_PREFIX + userTempId);
            }
        }
    }

    @Override
    public void checkCartSize(String cartKey) {
        Long size = redisTemplate.opsForHash().size(cartKey);
        if(size >= RedisConst.CART_SIZE){
//            throw new CartSizeOverException(ResultCodeEnum.CART_SIZE_OVER);
            throw new GmallException(ResultCodeEnum.CART_SIZE_OVER);
        }
    }

    @Override
    public void checkAllSize(String userId, String userTempId) {
        Long size1 = redisTemplate.opsForHash().size(RedisConst.USER_CART_KEY_PREFIX + userId);
        Long size2 = redisTemplate.opsForHash().size(RedisConst.USER_CART_KEY_PREFIX + userTempId);
        if((size1+size2)>200L){
            throw new GmallException(ResultCodeEnum.CART_SIZE_OVER);

        }
    }

    private CartInfo convertSkuInfo2CartInfo(SkuInfo skuInfo, Integer skuNum) {
        CartInfo cartInfo = new CartInfo();
//        cartInfo.setUserId();
        cartInfo.setSkuId(skuInfo.getId());
        cartInfo.setCartPrice(skuInfo.getPrice());
        cartInfo.setSkuNum(skuNum);
        cartInfo.setImgUrl(skuInfo.getSkuDefaultImg());
        cartInfo.setSkuName(skuInfo.getSkuName());
        cartInfo.setIsChecked(1);
        cartInfo.setCreateTime(new Timestamp(System.currentTimeMillis()));
        cartInfo.setUpdateTime(new Timestamp(System.currentTimeMillis()));
        cartInfo.setSkuPrice(skuInfo.getPrice());
//        cartInfo.setCouponInfoList();
        return cartInfo;
    }
}
